package game.view;

import game.dialog.DialogController;
import game.input.MovementController;
import game.models.WaterMovementBehaviour;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JFrame;

import renderer.MapRenderer;

import console.view.CommandHandler;

import accessory.CLog;
import accessory.Command;
import accessory.cres.CResNode;

import map.GameMap;
import map.PlayerEntity;
import map.RasterCell;

public class MainFrame extends JFrame {
		
	//constants
	private static final String GRAFICS_LOADING_FRAME_WIDTH_STRING = "loading_frame_width";
	private static final String GRAFICS_LOADING_FRAME_HEIGHT_STRING = "loading_frame_height";
	private static final String GRAFICS_CONTENT_FRAME_WIDTH_STRING = "content_frame_width";
	private static final String GRAFICS_CONTENT_FRAME_HEIGHT_STRING = "content_frame_height";
	private static final String GRAFICS_CONTENT_FRAME_FULLSCREEN = "content_frame_fullscreen";
	
	private CResNode graficsNode;
	private MovementController movementController;
	private HashMap<String, GameCanvas> maps;

	private PlayerEntity playerObject;
	
	public MainFrame(CResNode graficsNode){
		playerObject = new PlayerEntity();
		this.graficsNode = graficsNode;
		this.maps = new HashMap<String, GameCanvas>();
		this.movementController = new MovementController(playerObject);
		
		
		final DialogController dialogController = new DialogController();
		
		int dialogWidth = Integer.parseInt(graficsNode.getNodeValue("dialog_width"));
		int dialogheight = Integer.parseInt(graficsNode.getNodeValue("dialog_height"));

		int dialogX = Integer.parseInt(graficsNode.getNodeValue("dialog_x"));
		int dialogY = Integer.parseInt(graficsNode.getNodeValue("dialog_y"));

		dialogController.setRenderUnitBounds(new Rectangle(dialogX, dialogY, dialogWidth, dialogheight));
				
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);	
		addKeyListener(movementController);
		
		//################ Keyboad Commands
		movementController.addAction("SHOW_ROSTER", new KeyboardCommand() {
			@Override
			public void execute() {
				CLog.info("Roster opened");
			}
		});
		
		movementController.addAction("SURF", new KeyboardCommand() {
			@Override
			public void execute() {
				playerObject.setActiveMovementBehaviour(new WaterMovementBehaviour(playerObject));
			}
		});
		
		movementController.addAction("CONFIRM", new KeyboardCommand() {
			@Override
			public void execute() {
				boolean ret = dialogController.next();
				if(!ret){
					CLog.info("No Text");
				}
			}
		});
		
		//############ Console Commands
		CommandHandler.addCommand("quit", new Command() {
			@Override
			public String execute(String[] args) {
				System.exit(0);
				return "exit";
			}
		});
		
		CommandHandler.addCommand("renderdialog", new Command() {
			@Override
			public String execute(String[] args) {
				if(args.length < 2){
					return "invalid syntax! use 'renderdialog <token> <...>'" ;
				}
				else {
					ArrayList<String> contents = new ArrayList<String>();
					for(int i = 1; i < args.length; i++){
						contents.add(args[i]);
					}
					DialogController.showDialog(contents);
					return "dialog activated";
				}
			}
		});
		
		CommandHandler.addCommand("renderengine", new Command() {
			
			@Override
			public String execute(String[] args) {
				if(args.length < 2){
					return "invalid syntax! use 'renderengine <class>'" ;
				}
				
			    
				try {
					Class c = Class.forName("renderer."+args[1]);
					MapRenderer render = (MapRenderer) c.newInstance();
					
									
				} catch (Exception e) {
					//e.printStackTrace();
					return "error during instantiation: " + e.getClass().getCanonicalName() + ":" + e.getMessage();
				} 
				
				return "set render to " + args[1];
			}
		});
	}

	
	public void loadGameContents(String mapName, GameMap map){
		setTitle("Game - "+mapName);
		
		if(!Boolean.parseBoolean(graficsNode.getNodeValue(GRAFICS_CONTENT_FRAME_FULLSCREEN))){
			resizeFrame(Integer.parseInt(graficsNode.getNodeValue(GRAFICS_CONTENT_FRAME_WIDTH_STRING)),  Integer.parseInt(graficsNode.getNodeValue(GRAFICS_CONTENT_FRAME_HEIGHT_STRING)));
						
		} else {
			//TODO:
			resizeFrame(1920, 1080);
		}
		
		if(maps.get(mapName) == null){
			GameCanvas canvas = new GameCanvas(map.getMapRaster(), playerObject);
			canvas.setSize(getWidth(), getHeight());
			canvas.setFocusable(true);
			setContentPane(canvas);
			movementController.setCanvas(canvas);
			maps.put(mapName, canvas);
		
			DialogController.setGraphicContainer(canvas.getGraphics());
			
			playerObject.setActiveMap(map.getMapRaster());
			playerObject.setPosition(canvas.getPov());
			
			canvas.addKeyListener(new MovementController(playerObject));
		}
	}


	public void loadDialog() {
		setTitle("Loading...");
		resizeFrame(Integer.parseInt(graficsNode.getNodeValue(GRAFICS_LOADING_FRAME_WIDTH_STRING)),  Integer.parseInt(graficsNode.getNodeValue(GRAFICS_LOADING_FRAME_HEIGHT_STRING)));

	}
	
	private void resizeFrame(int width, int height){
		setBounds(new Rectangle(width, height));
	}
}
